package ITS;

use Data::Dumper;
use strict;
use warnings;

# Export the public subroutines to programs that use this module
BEGIN {
	require Exporter;
	our @ISA    = qw(Exporter);
	our @EXPORT = qw();
}

my $cmd;                   #polarion command line
my $server;                #polarion path
my $release;               #increment
my $project;               #project name
my $base_open_wi_allow;    #open work items flag
my $buildReport;           #build report file
my $work_item_rev_ref;

###############################################################################
# Function: accessITS
# This subroutine gets the work items from Polarion. If it's a cron can be any
# committed work item. If it's a baseline can just be the closed work items. This
# function also calls wiWarnings() to see if there's an open work item related to
# the increment, when it's a baseline
#
# Inputs: Polarion path, project,increment, build type, base_open_wi_allow, buildReport
# Returns: Nothing.
###############################################################################

sub accessITS {

	$server  = $_[1];
	$project = $_[2];
	$release = $_[3];
	my $type = $_[4];
	$base_open_wi_allow = $_[5];
	$buildReport        = $_[6];

	if ( $type eq "cron" ) {
		$cmd =
"polarion_export --server $server --query \"project.id:$project AND fw_release:$release AND CodeCommit:true\" --fields \"id,linkedRevisions\" |";
	}
	elsif ( $type eq "baseline" ) {
		print "Searching for open work items.  Please wait.  This will take some time...\n";
		wiWarnings();
		$cmd =
"polarion_export --server $server --query \"project.id:$project AND fw_release:$release AND CodeCommit:true AND status:closed\" --fields \"id,linkedRevisions\" |";
	}
}

###############################################################################
# Function: WorkItemRevTohash
# This subroutine uses the polarion command line and coverts the result into a
# hash
# Additional Information:
#
# 1) - Format of the command line result:
#
# id      linkedRevisions
# PG-29   9895,9910,9926,9956,9950,9949,10365
# PG-28   9890
#
# 2) - There are three scenarios in this case:
#
# 1- No revisions: WORK ITEM -> NO REVISION
# 2- More than one revision (separated by comma): WORK ITEM -> REV1,REV2,REV3,REV4....
# 3- Just one revision: WORK ITEM -> REV1
#
# 3) - @wi_rev_name_key
#
# $wi_rev_key[0] = 'id'
# $wi_rev_key[1] = 'linkedRevisions'
#
# 4) - @wi_rev_values fornat:
# First loop
#
# $wi_rev_values[0] = 'PG-28'
# $wi_rev_values[1] = '9890'
#
# Second loop
# $wi_rev_values[0] = 'PG-29'
# $wi_rev_values[1] = '9895,9910,9926,9950,9949,10365'
#
# 5) - Work_item_rev format:
#
# id => ['PG-28','PG-29']
# linkedRevisions => ['9890',
#					  '9895,9910,9926,9950,9949,10365']
#
# Inputs: Command line
# Returns: Pointer to work_item_rev hash
###############################################################################

sub WorkItemRevTohash {
	my %work_item_rev;
	my $cmd = $_[0];
	open( CMD, $cmd );

	#For command line result format, see subroutine description 1 and 2.
	my $line = <CMD>;
	if ( defined $line ) {
		chomp $line;

   #Get the name of the keys in the first line: id and linkedRevisions. So there
   # are two keys here. See subroutine description 3 for more details.
		my @wi_rev_keys = split /	/, $line;

		while ( $line = <CMD> ) {
			chomp $line;

			#The val[0] will be the work item id related to the first key
			# and the val[1] will be the revisions related to the second key
			#See subroutine description 4.
			my @wi_rev_values = split /	/, $line;

			#For each line in the result, the tool stores the 2 values related
			#to the keys: work item id and revisions
			for ( my $i = 0 ; $i <= $#wi_rev_values ; $i++ ) {
				push @{ $work_item_rev{ $wi_rev_keys[$i] } },
				  $wi_rev_values[$i];
			}

		}
		close(CMD);
	}

	#print Data::Dumper->Dump( [ \%hash ], [qw/hash/] );
	print "\n-------------------------------------------------------\n";
	print "           WORK ITEM - LINKED REVISIONS                  \n";
	print "-------------------------------------------------------\n\n";
	print Dumper( \%work_item_rev );

	#For work_item_rev format, see subroutine description 5.
	return \%work_item_rev;
}

###############################################################################
# Function: getRevisions
# This subroutine gets all the revisions based on the pointer to the work_item_rev
# hash returned by the WorkItemRevTohash subroutine. If the build type is a baseline
# and there's no linked revisions the tool will fail
#
# Additional Information:
#
# 1) - @rev format:
#
#    @rev = ['9890', '9895,9910,9926,9950,9949,10365']
#
# It needs to separate the revisions in @rev[1]
#
# 2) - @rev_list format:
#
#    @rev_list = ['9890', '9895','9910','9926','9950','9949','10365']
#
# Inputs: Build type
# Returns: Revision array
###############################################################################

sub getRevisions {

	my @rev;
	my @new_rev;
	my @rev_list = ();

	#Get work item/ revisions hash
	$work_item_rev_ref = WorkItemRevTohash($cmd);
	if ( defined $work_item_rev_ref ) {
		my %work_item_rev = %$work_item_rev_ref;
		

	#Get all work items revisions from the work_item_rev hash
	#There are two keys in the work_item_rev hash: id and linkedRevisions.
	#Since the tool only needs the values of the second key, the keys are sorted
	#and the value of @rev will be just related to the linkedRevisions
		foreach my $key ( sort keys %work_item_rev ) {

			@rev = @{ $work_item_rev{$key} };
		}

#The tool gets the revisions separated by "," because when the work item has more than one revision,
#ITS separates them by comma. See subroutine description 1.
#it separates them by comma. See subroutine description 1.
		for ( my $i = 0 ; $i < scalar(@rev) ; $i++ ) {

			#If there is a revision separated by "," it will be splitted
			@new_rev = split( ',', $rev[$i] );
			for ( my $j = 0 ; $j < scalar(@new_rev) ; $j++ ) {

				#Add all the revisions
				push( @rev_list, $new_rev[$j] );
			}
		}
	}

	#See subroutine description 2 for @rev_list format
	return \@rev_list;
}

###############################################################################
# Function: wiWarnings
# This subroutine analyzes if there're open work items related to the increment
# when it's a baseline. If the base_open_wi_allow is enabled the tool will print
# a warning. If it's not, tool will delete the tags and buindInfo.txt and then fail.
#
# Inputs: Nothing.
# Returns: Nothing.
###############################################################################

sub wiWarnings {

	#Get the open work items
	$cmd =
"polarion_export --server $server --query \"project.id:$project AND fw_release:$release AND CodeCommit:true AND status:open\" --fields \"id,linkedRevisions\" |";

	#Get the revisions related to the opened work items
	my $rev_list_ref = getRevisions();
	if ( defined $rev_list_ref ) {
		my @rev_list = @$rev_list_ref;

		#Test if exists linked revisions to the work item
		if ( $rev_list[0] ) {

			#If the flag is enabled it will send a warning
			if ( $base_open_wi_allow eq "true" ) {
				print
				  "Warning: There are opened files related to this increment\n";
			}
			else {

				#If the flag is not enabled, the tool will fail
				system("rm -rf tags");
				system("rm -rf buildInfo.txt");
				die
"\nError: Can't create baseline build because there are opened work items in the increment that have code attached and the base_open_wi_allow flag is not set \n";
			}
		}
	}
}

###############################################################################
# Function: updateBuildReport
# This subroutine inserts the work items and linked revisions into the build
# report.
#
# Inputs: Referece to the work item -> linked revisions hash
# Returns: Nothing.
###############################################################################

sub updateBuildReport {
	my %work_item_rev = %$work_item_rev_ref; 
	my @wi_id = @{$work_item_rev{'id'}};
	my @wi_rev = @{$work_item_rev{'linkedRevisions'}};

	#Insert the work items - linked revisions into the file
	open( FILE, ">>$buildReport" );
	print FILE "WORK ITEMS: ";
	my $wi_id;
	foreach $wi_id (@wi_id){
		print FILE $wi_id, " ";
	}
	print FILE "\nLINKED REVISIONS: ";
	my $wi_rev;
	foreach $wi_rev (@wi_rev){
		print FILE $wi_rev, " ";
	}
	close FILE;

}

1;

